﻿//*****************************************************************************
// Source: http://www.codeproject.com/KB/WF/DynamicSendActivity.aspx
//*****************************************************************************
//
using System;
using System.Activities;
using System.Activities.Presentation.Model;
using System.Diagnostics;
using System.Globalization;
using System.Windows.Data;
using System.Xml.Linq;

namespace TfsCloudDeploy.Workflow.Core.Converters
{
    [ValueConversion(typeof(XElement), typeof(string))]
    public class XmlArgumentToExpressionConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            object convertedValue = null;

            try
            {
                if (value != null)
                {
                    ModelItem item = value as ModelItem;
                    if (((item != null) && (item.Properties["Expression"] != null)) && (item.Properties["Expression"].Value != null))
                    {
                        var currentValue = item.Properties["Expression"].ComputedValue;
                        dynamic vbValue = currentValue;

                        // make xml formatted text
                        if (vbValue != null)
                        {
                            if (string.IsNullOrEmpty(vbValue.ExpressionText) == false && vbValue.ExpressionText.Trim().StartsWith("<"))
                            {
                                vbValue.ExpressionText = XDocument.Parse(vbValue.ExpressionText).ToString(SaveOptions.None | SaveOptions.OmitDuplicateNamespaces);
                            }

                        }
                        convertedValue = item.Properties["Expression"].Value;
                    }
                }
                else
                    Trace.WriteLine(string.Format("Convert: Value to be converted is null"));
            }
            catch (Exception exception)
            {
                Trace.WriteLine(exception.ToString());
                throw;
            }

            return convertedValue;
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            Argument argument = null;
            ArgumentDirection argumentDirection = ArgumentDirection.In;
            string str = parameter as string;
            if (!string.IsNullOrEmpty(str))
            {
                argumentDirection = (ArgumentDirection)Enum.Parse(typeof(ArgumentDirection), str);
            }
            Activity currentValue = null;
            ModelItem item = value as ModelItem;
            if ((item != null) && typeof(Activity).IsAssignableFrom(item.ItemType))
            {
                currentValue = (Activity)item.GetCurrentValue();
            }
            ActivityWithResult result = currentValue as ActivityWithResult;
            if ((currentValue != null) && (result != null))
            {
                Type expressionType;
                if (argumentDirection == ArgumentDirection.In)
                {
                    expressionType = result.ResultType;
                }
                else if (result.ResultType.IsGenericType)
                {
                    expressionType = result.ResultType.GetGenericArguments()[0];
                }
                else
                {
                    expressionType = result.ResultType;
                }
                try
                {
                    dynamic vbValue = currentValue;
                    //var vbValue = currentValue as VisualBasicValue<XElement>;

                    if (string.IsNullOrEmpty(vbValue.ExpressionText) == false && vbValue.ExpressionText.Trim().StartsWith("<"))
                    {
                        vbValue.ExpressionText = XDocument.Parse(vbValue.ExpressionText).ToString(SaveOptions.DisableFormatting | SaveOptions.OmitDuplicateNamespaces);
                    }

                    argument = Argument.Create(expressionType, argumentDirection);
                    argument.Expression = vbValue;
                }
                catch (Exception exception)
                {
                    Trace.WriteLine(exception.ToString());
                    throw;
                }
            }
            return argument;
        }
    }
}